home *** CD-ROM | disk | FTP | other *** search
/ Gigarom 1 / Gigarom Macintosh Archives (Quantum Leap)(CDRM1080320)(1993).iso / FILES / DEV / A-B / Anim Cursor.cpt / pascal / CursorCtl.lsp < prev   
Text File  |  1990-01-22  |  6KB  |  198 lines

  1. unit CursorCtl;
  2.  
  3. {Routines to use an animated cursor}
  4.  
  5. interface
  6.  
  7.     type
  8.         acur = record
  9.             frameCount: integer;    {Number of frames in animation sequence}
  10.             whichFrame: integer;    {Current frame}
  11.             frame: array[1..1] of CursHandle;    {the list of "CURS" resources representing sequence (IDs and handles)}
  12.         end;
  13.         acurPtr = ^acur;
  14.         acurHandle = ^acurPtr;
  15.  
  16.     var
  17.         FrameList: acurHandle;    {handle to "acur" resource}
  18.         CursVBL: VBLTask;    {VBL task to handle cursor animation}
  19.         CursAnimationEnabled: BOOLEAN;    {True if able to load "acur" and associated "CURS" resources}
  20.         CursSpeed: INTEGER;        {Number of ticks between consecutive cursor frames}
  21.         CursAlreadyOn: BOOLEAN;    {True if cursor animation is already running}
  22.  
  23.     procedure InitCursAnimation (acurID: INTEGER    {Rsrc ID of "acur" resource}
  24.                                     );
  25.     procedure AnimateCursor (speed: INTEGER        {ticks between consecutive frames}
  26.                                     );
  27.     procedure StopCursor;
  28.  
  29.  
  30. implementation
  31.  
  32. {============ SetCurrentA5 ==============================================}
  33.  
  34. {This routine sets up the A5 to point to the boundary between the application globals }
  35. { and the application parameters. It returns the previous value of A5. This function is}
  36. {used instead of SetUpA5 which is dangerous as it does not return the old value of A5}
  37. {but rather leaves it on the stack-see tech note #208 for more details}
  38.  
  39.     function SetCurrentA5: Longint;
  40.     inline
  41.         $2E8D, $2A78, $0904;
  42.  
  43. {============ SetA5 ==============================================}
  44.  
  45. { This routine sets the value of A5 to "newA5". It should be used to restore the old value }
  46. {of A5 at the end of a completion routine or a VBL task. It also returns the previous value}
  47. { of A5. This function is used instead of RestoreA5 which assumes the old value of A5}
  48. {is still on the stack-see tech note #208 for more details}
  49.  
  50.     function SetA5 (newA5: Longint): Longint;
  51.     inline
  52.         $2F4D, $0004, $2A5F;
  53.  
  54. {============ SetWatchCursor ==================================================}
  55.  
  56.     procedure SetWatchCursor;
  57.  
  58.         var
  59.             mycursor: CursHandle;
  60.  
  61.     begin
  62.         mycursor := GetCursor(watchCursor);
  63.         SetCursor(mycursor^^);
  64.     end; {SetWatchCursor}
  65.  
  66. {============ InitCursAnimation =====================================================}
  67.  
  68. {This procedure tries to load the "acur" resource and if found tries to load all the "CURS" resources}
  69. {listed in the "acur" resource}
  70.  
  71.     procedure InitCursAnimation (acurID: INTEGER    {Rsrc ID of "acur" resource}
  72.                                     );
  73.  
  74.         var
  75.             i, errorcode: integer;
  76.  
  77.     begin
  78.         FrameList := acurHandle(GetResource('acur', acurID));    {Get the "acur" resource}
  79.         errorcode := ResError;
  80.  
  81.         if FrameList = nil then
  82.             errorcode := ResNotFound;
  83.  
  84.         if errorcode = noErr then
  85.             begin
  86.                 i := 1;
  87.                 while (i <= FrameList^^.frameCount) and (errorcode = noErr) do
  88.                     begin
  89.         {Get the "CURS" resources whose ID's are in the high word of the frame field.  Store handle to these}
  90.         {resources in the same frame field}
  91.                         FrameList^^.frame[i] := GetCursor(HiWord(LONGINT(FrameList^^.frame[i])));
  92.                         errorcode := ResError;
  93.                         if FrameList^^.frame[i] = nil then
  94.                             errorcode := ResNotFound;
  95.                         i := SUCC(i);
  96.                     end;
  97.                 FrameList^^.whichframe := 1;    {Set initial frame}
  98.             end;
  99.  
  100.         CursAnimationEnabled := errorcode = noErr;    {True if no error is found}
  101.     end;    {InitCursAnimation}
  102.  
  103. {============ CursorAnimationVBL =====================================================}
  104.  
  105. {VBL routine to set the cursor to the next cursor in the animation sequence}
  106.  
  107.     procedure CursorAnimationVBL;
  108.  
  109.         var
  110.             oldA5: LONGINT;
  111.  
  112.     begin
  113.         oldA5 := SetCurrentA5;
  114.  
  115. {FrameList and all frame handles are assumed to be locked}
  116.         with FrameList^^ do
  117.             begin
  118.                 SetCursor(frame[whichFrame]^^);
  119.  
  120.                 whichFrame := SUCC(whichFrame);
  121.                 if whichFrame > frameCount then
  122.                     whichFrame := 1;
  123.             end;    {with}
  124.         CursVBL.vblCount := CursSpeed;    {Reinstall the VBL}
  125.  
  126.         oldA5 := SetA5(oldA5);
  127.     end;    {CursorAnimationVBL}
  128.  
  129. {============ AnimateCursor =====================================================}
  130.  
  131. {Install out task in the vertical retrace queue unless cursor animation is not enabled then use watch cursor}
  132.  
  133.     procedure AnimateCursor (speed: INTEGER        {ticks between consecutive frames}
  134.                                     );
  135.  
  136.         var
  137.             errorcode, i: integer;
  138.  
  139.     begin
  140.         if not CursAlreadyOn then
  141.             begin
  142.                 CursAlreadyOn := TRUE;
  143.  
  144.                 if CursAnimationEnabled then
  145.                     begin
  146.     {Lock all handles that will be accessed from the VBL}
  147.                         HLock(Handle(FrameList));
  148.                         for i := 1 to FrameList^^.frameCount do
  149.                             HLock(Handle(FrameList^^.frame[i]));
  150.  
  151.                         FrameList^^.whichframe := 1;    {Set initial frame}
  152.  
  153.     {Set up the VBL task fields and install it}
  154.                         with CursVBL do
  155.                             begin
  156.                                 qType := ORD(vType);
  157.                                 vblAddr := @CursorAnimationVBL;
  158.                                 vblCount := speed;     {next VBL after "speed" ticks}
  159.                                 vblPhase := 0;
  160.                             end;    {with}
  161.                         errorcode := VInstall(@CursVBL);
  162.  
  163.                         CursSpeed := speed;    {Set the speed of animation}
  164.                     end
  165.                 else    {Use watch cursor}
  166.                     SetWatchCursor;
  167.             end;    {if}
  168.     end;    {AnimateCursor}
  169.  
  170. {============ StopCursor =====================================================}
  171.  
  172. {remove the VBL task from the vertical retrace queue and restore the arrow cursor}
  173.  
  174.     procedure StopCursor;
  175.  
  176.         var
  177.             errorcode, i: integer;
  178.  
  179.     begin
  180.         if CursAlreadyOn then
  181.             begin
  182.                 CursAlreadyOn := FALSE;
  183.  
  184.                 if CursAnimationEnabled then
  185.                     begin
  186.                         errorcode := VRemove(@CursVBL);
  187.  
  188.     {Unlock all handles that were locked before VBL installation}
  189.                         HUnLock(Handle(FrameList));
  190.                         for i := 1 to FrameList^^.frameCount do
  191.                             HUnLock(Handle(FrameList^^.frame[i]));
  192.                     end;    {if}
  193.  
  194.                 InitCursor;
  195.             end;    {if}
  196.     end;    {StopCursor}
  197.  
  198. end.